package easy.netty.net.core;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author cengy
 */
public abstract class Endpoint
        extends ChannelInitializer<Channel>
        implements IoSession, IoService {

    private
    static
    final Logger logger = LoggerFactory.getLogger(Endpoint.class);

    protected IoConf ioConf;
    protected IoService ioService;
    protected IoMgr ioMgr;

    protected void head(Channel ch) throws Exception {
        ChannelPipeline p = ch.pipeline();
        final IoConf conf = ioConf;
        p.addLast("idleCheck",
                new IdleStateHandler(conf.getReadIdle(),
                        conf.getWriteIdle(),
                        conf.getAllIdle()));
    }

    @Override
    protected void initChannel(Channel ch) throws Exception {

        head(ch);
        initChannel0(ch);
        tail(ch);
    }

    protected void initChannel0(Channel ch) throws Exception {

    }

    protected void tail(Channel ch) throws Exception {
        ChannelPipeline p = ch.pipeline();
        p.addLast("ioHandler", newHandler());
    }

    @Override
    public void open() {
        boolean started = false;
        if (null != ioService) {
            if (ioConf.isEnable()) {
                ioService.open();
                started = true;
            }
        }
        if (!started) {
            logger.warn("cant start {}, maybe no instance IoService or IoConf.enable = false",
                    this.getClass().getSimpleName());
        }
        if (started) {
            ioMgr = new IoMgr();
        }
    }

    @Override
    public void close() {

        if (null != ioService) {
            ioService.close();
        }
    }

    protected ChannelHandler newHandler() {
        return new IoHandler(this);
    }
    //------------------------------------------------------

    public void channelActive(IoSession session) {
        session.onOpen();
    }

    public void channelInActive(IoSession session) {
        session.onClose();
    }

    public void channelRead(IoSession session, Object message) {
        session.onRead(message);
    }

    public void channelEvent(IoSession session, Object evt) {
        session.onEvt(evt);
    }

    public void channelError(IoSession session, Throwable t) {
        session.onError(t);
    }
    //------------------------------------------------------


    public IoConf getIoConf() {
        return ioConf;
    }

    public void setIoConf(IoConf ioConf) {
        this.ioConf = ioConf;
    }

    public IoService getIoService() {
        return ioService;
    }

    public void setIoService(IoService ioService) {
        this.ioService = ioService;
    }

    public IoMgr getIoMgr() {
        return ioMgr;
    }

    public void setIoMgr(IoMgr ioMgr) {
        this.ioMgr = ioMgr;
    }

}
